﻿using SqlSugar;
using System.Collections.Generic;

namespace Magic.System;
/// <summary>
/// 菜单服务
/// </summary>
[Injection]
public class MenuService : IMenuService
{
    private readonly ICacheService _cacheService;
    public MenuService(ICacheService cacheService)
    {
        _cacheService = cacheService;
    }
    public async Task<List<MenuOutput>> GetTree(List<int> ids = null, bool all = false, string quick_search = "")
    {
        var menus = await SugarContext.Instance
            .Queryable<SysMenu>()
            .WhereIF(!all, m => m.Status == "1")
            .WhereIF(!string.IsNullOrEmpty(quick_search), p => p.Title.Contains(quick_search))
            .WhereIF(ids != null && ids.Any(), m => ids.Contains(m.Id))
            .OrderBy(m => m.Sort)
            .Select<MenuOutput>()
            .ToListAsync();

        //这里如果不是获取全部，说明是返回权限菜单，需要把keepalive转换为path，否则设置路由缓存前端不生效
        if (!all)
        {
            menus.ForEach(m =>
            {
                m.Keepalive = m.Keepalive == "1" ? m.Path : m.Keepalive;
            });
        }


        return new TreeBuildUtil<MenuOutput>().DoTreeBuild(menus);
    }
    /// <summary>
    /// 分页返回菜单
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<dynamic> GetPageList(MenuInput input)
    {
        var menuRules = await SugarContext.Instance.Queryable<SysMenu>()
            .Where(p => p.Type != "button")
            .OrderBy(p => p.Sort)
            .ToListAsync();
        //校验数据
        _ = menuRules ?? throw new ApiException("");
        //根据层级生成前缀
        int spanceCount = 1;//空格个数
        int? pid = 0;
        string prexString = string.Empty;
        menuRules.ForEach(menuRule =>
        {
            if (menuRule.Pid != 0 && menuRule.Pid != pid)
            {
                prexString = string.Empty.PadRight(spanceCount, (char)32);//char32 空格
                pid = menuRule.Pid;
                menuRule.Title = string.Concat(prexString, string.Concat("└", menuRule.Title));
                spanceCount++;
            }
            else if (menuRule.Pid != 0 && menuRule.Pid == pid)
            {
                menuRule.Title = string.Concat(prexString, string.Concat("└", menuRule.Title));
            }
        });
        return new
        {
            options = menuRules
        };
    }
    /// <summary>
    /// 根据Id返回菜单
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<dynamic> Get(int id)
    {
        var menuRole = await SugarContext.Instance.Queryable<SysMenu>()
                .FirstAsync(p => p.Id == id);
        //数据校验
        _ = menuRole ?? throw new ApiException("");
        return menuRole;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public async Task Delete(List<int> ids)
    {
        if (ids.Count == 0)
            throw new ApiException("删除分组Id不能为空");
        //获取待删除分组集合
        var menuRules = await SugarContext.Instance.Queryable<SysMenu>()
            .Where(p => ids.Contains(p.Id))
            .ToListAsync();
        //判断删除数据与传入数据总数是否一致
        if (ids.Count != menuRules.Count)
            throw new ApiException("传入删除数据与真实数据不一致，请刷新再试");
        await SugarContext.Instance.Deleteable<SysMenu>().Where(p => ids.Contains(p.Id)).ExecuteCommandAsync();
    }
    /// <summary>
    /// 新增菜单规则
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task Add(AddMenuRuleInput input)
    {
        if (await SugarContext.Instance.Queryable<SysMenu>().AnyAsync(m => m.Pid == input.Pid && m.Name == input.Name))
        {
            throw new ApiException("相同规则名称已存在");
        }
        await SugarContext.Instance.Insertable<SysMenu>(input.Adapt<SysMenu>()).ExecuteCommandAsync();
    }
    /// <summary>
    /// 菜单规则编辑
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task Edit(EditMenuRuleInput input)
    {
        var menuRule = await SugarContext.Instance.Queryable<SysMenu>().AnyAsync(p => p.Id == input.Id);
        if (!menuRule)
            throw new ApiException("菜单不存在");

        if (await SugarContext.Instance.Queryable<SysMenu>().AnyAsync(m => m.Pid == input.Pid && m.Name == input.Name && m.Id != input.Id))
        {
            throw new ApiException("相同规则名称已存在");
        }

        var editMenuRule = input.Adapt<SysMenu>();
        await SugarContext.Instance.Updateable<SysMenu>(editMenuRule)
            .Where(p => p.Id == input.Id)
            .IgnoreColumns(true)
            .ExecuteCommandAsync();
    }
    /// <summary>
    /// 菜单排序
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task Sort(SortMenuRuleInput input)
    {
        var menuRule = await SugarContext.Instance.Queryable<SysMenu>().FirstAsync(p => p.Id == input.Id);
        var targetMenuRule = await SugarContext.Instance.Queryable<SysMenu>().FirstAsync(p => p.Id == input.TargetId);
        _ = menuRule ?? throw new ApiException("原始菜单不存在");
        _ = targetMenuRule ?? throw new ApiException("目标菜单不存在");

        var sort = menuRule.Sort;
        var tarSort = targetMenuRule.Sort;
        menuRule.Sort = tarSort;
        targetMenuRule.Sort = sort;

        SugarContext.Instance.Updateable<SysMenu>(new List<SysMenu> { menuRule, targetMenuRule }).UpdateColumns(it => new { it.Sort }).ExecuteCommand();
    }
    /// <summary>
    /// 获取所有权限集合
    /// </summary>
    /// <returns></returns>
    public async Task<List<string>> GetAllPermission()
    {
        var permissions = await _cacheService.GetAllPermission();
        if (permissions == null || permissions.Count == 0)
        {
            permissions = await SugarContext.Instance.Queryable<SysMenu>()
            .Where(p => p.Type == MenuTypeConst.Button)
            .Where(p => p.Status == "1")
            .Select(p => p.Name)
            .ToListAsync();
        }
        //设置缓存
        await _cacheService.SetAllPermission(permissions);
        return permissions;
    }
    /// <summary>
    /// 获取权限缓存（按钮）
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    public async Task<List<string>> GetPermission(long userId)
    {
        var permissions = await _cacheService.GetPermission(userId);
        if (permissions == null || permissions.Count == 0)
        {
            //获取用户拥有的所有
            var rules = await SugarContext.Instance.Queryable<SysUser, SysRole, SysUserRole>((a, ag, aga) =>
             a.Id == aga.Uid && ag.Id == aga.RoleId)
                 .Where((a, ag, aga) => a.Id == userId)
                 .Select((a, ag, aga) => ag.Permissions)
                 .Distinct()
                 .ToListAsync();
            var userRuls = string.Join(",", rules.SelectMany(s => s.Split(','))
                .Distinct()).Split(',');
            permissions = await SugarContext.Instance.Queryable<SysMenu>()
                .Where(p => userRuls.Contains(p.Id.ToString()))
                .Where(p => p.Type == MenuTypeConst.Button)
                .Select(p => p.Name)
                .ToListAsync();
            await _cacheService.SetPermission(userId, permissions);
        }
        return permissions;
    }
}
